package com.kinsin.kinsinutil

import android.content.Context
import android.content.res.Resources
import android.util.DisplayMetrics
import com.kinsin.kinsinutil.DimenUtils.dpToPx
import com.kinsin.kinsinutil.DimenUtils.pxToDp
import com.kinsin.kinsinutil.DimenUtils.pxToSp
import com.kinsin.kinsinutil.DimenUtils.spToPx
import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import kotlin.math.roundToInt

class DimenUtilsTest {
    private val mockResources = mockk<Resources>()
    private val mockContext = mockk<Context>()
    private val normalMetrics = DisplayMetrics().apply {
        density = 1.5f
        scaledDensity = 1.2f
        widthPixels = 1080
        heightPixels = 1920
    }
    private val zeroMetrics = DisplayMetrics().apply {
        density = 0f
        scaledDensity = 0f
        widthPixels = 0
        heightPixels = 0
    }

    @Before
    fun setup() {
        every { mockResources.displayMetrics } returns normalMetrics
        every { mockContext.resources } returns mockResources
    }

    @Test
    fun `dp to px conversions`() {
        // Normal cases
        assertEquals(24, 16.dpToPx(mockResources))
        assertEquals(24, 16.dpToPx(mockContext))
        assertEquals(18, 12.3f.dpToPx(mockResources))
        assertEquals(19, 12.6f.dpToPx(mockResources))
    }

    @Test
    fun `px to dp conversions`() {
        assertEquals(10, 15.pxToDp(mockResources))
        assertEquals(10, 15.pxToDp(mockContext))
        assertEquals(8, 12.3f.pxToDp(mockResources))
        assertEquals(8, 12.6f.pxToDp(mockResources))
    }

    @Test
    fun `sp to px conversions`() {
        assertEquals(14, 12.spToPx(mockResources))
        assertEquals(14, 12.spToPx(mockContext))
        assertEquals(15, 12.3f.spToPx(mockResources))
        assertEquals(15, 12.6f.spToPx(mockResources))
    }

    @Test
    fun `px to sp conversions`() {
        assertEquals(12, 14.pxToSp(mockResources))
        assertEquals(12, 14.pxToSp(mockContext))
        assertEquals(10, 12.3f.pxToSp(mockResources))
        assertEquals(11, 12.6f.pxToSp(mockResources))
    }

    @Test
    fun `screen dimensions`() {
        assertEquals(1080, DimenUtils.getScreenWidth(mockResources))
        assertEquals(1080, DimenUtils.getScreenWidth(mockContext))
        assertEquals(1920, DimenUtils.getScreenHeight(mockResources))
        assertEquals(1920, DimenUtils.getScreenHeight(mockContext))
    }

    @Test
    fun `zero density cases`() {
        // 模拟density和scaledDensity为0的情况
        every { mockResources.displayMetrics } returns zeroMetrics

        // 测试dp转换
        assertEquals(0, 16.dpToPx(mockResources))
        assertEquals(0, 16.dpToPx(mockContext))
        assertEquals(0, 15.pxToDp(mockResources))

        // 测试sp转换
        assertEquals(0, 12.spToPx(mockResources))
        assertEquals(0, 14.pxToSp(mockResources))

        // 测试屏幕尺寸
        assertEquals(0, DimenUtils.getScreenWidth(mockResources))
        assertEquals(0, DimenUtils.getScreenHeight(mockContext))
    }

    @Test
    fun `extreme values`() {
        // 使用明确的类型转换
        val maxInt = Int.MAX_VALUE

        // 测试pxToDp
        val pxValue = maxInt
        val expectedDp = (pxValue / normalMetrics.density).roundToInt()
        assertEquals(expectedDp, pxValue.pxToDp(mockResources))

        // 测试dpToPx
        val dpValue = maxInt
        val expectedPx = (dpValue * normalMetrics.density).roundToInt()
        assertEquals(expectedPx, dpValue.dpToPx(mockResources))

        // 测试负值
        assertEquals(-24, (-16).dpToPx(mockResources)) // -16 * 1.5 = -24
        assertEquals(-10, (-15).pxToDp(mockResources)) // -15 / 1.5 = -10
    }
}